package org.yawnage.framework 
{
	import flash.utils.Dictionary;
	import org.yawnage.base.BaseKeyMapper;
	import org.yawnage.framework.server.SubscriberObject;
	import org.yawnage.interfaces.base.IMapperObject;
	import org.yawnage.interfaces.framework.IBridge;
	import org.yawnage.interfaces.framework.ISubscriber;
	import org.yawnage.interfaces.framework.ITransportLayer;
	 /**
	  * <p>//TODO:To be written</p>
	  * @author Berry Jordaan
	  * @date 2011/09/06 10:22 AM
	  * @copyright  Copyright © Berry/James 2011
	  * @version 1.0.0.0
	  * @filename Broker.as 
	  * @description
	  * @history Berry Jordaan on 2011/09/06 10:22 AM: Created
	  */
	 public class Bridge extends BaseKeyMapper implements IMapperObject,IBridge
	{
		
		//************** Enums **************

		//************** Public *************
		
		//************** Private ************
		private var _service		:String;
		private var _publisher		:String;
		
		//************** protected **********
		
		/**
		 * Constructor
		 */
		public function Bridge(publisherName:String, service:String)
		{
			super();
			_service = service;
			_publisher = publisherName;
			setClassDescription("org.yawnage.framework.Bridge");
		}
		
		/**
		 * useless comment here!
		 */
		override public function dispose():void 
		{
			super.dispose();
		}
		
		/* INTERFACE org.yawnage.base.interfaces.framework.IBridge */
		
		public function forwardMessage(dataP:ITransportLayer = null):void 
		{
			var obj:SubscriberObject;
			var L:int = _mapperList.length;
			for (var i:int = 0; i < L ; i++) 
			{
				obj = SubscriberObject(_mapperList[i]);
				try{
					obj.method.apply(obj.subscriber, [dataP]);
				}catch (e:Error) {
					_trace("ERROR: Problem in component " + obj.subscriber+". Fix or unregister!", this, 0xFF0000);
					_trace(e.getStackTrace(), this, 0xFF0000);
				}
			}
		}
		
		/**
		 * 
		 * @param	dataP
		 */
		public function debugForwardMessage(dataP:ITransportLayer = null):void 
		{
			var obj:SubscriberObject;
			var L:int = _mapperList.length;
			for (var i:int = 0; i < L ; i++) 
			{
				obj = SubscriberObject(_mapperList[i]);
				try {
					if (Broker.publisherToTest == null || Broker.publisherToTest == _publisher) {
						_trace("[" + _publisher + "] syndicated Service [" + _service + "] to " + obj.subscriber + "  priority:"+obj.priority, this, 0x808080);
					}
					
					obj.method.apply(obj.subscriber, [dataP]);
				}catch (e:Error) {
					_trace("ERROR: Problem in component " + obj.subscriber+". Fix or unregister!", this, 0xFF0000);
					_trace(e.getStackTrace(), this, 0xFF0000);
				}
			}
			
			if (Broker.publisherToTest == null || Broker.publisherToTest == _publisher) {
				if (dataP != null && dataP.data != null) {
					_trace("      "+_publisher+" , service ["+_service+"] transport layer:", this, 0x8080C0);
					_trace(dataP.data, this, 0x808080);
				}else {
					_trace("     "+_publisher+" , service ["+_service+"] has no transport layer", this, 0x8080C0);
				}
			}
		}
		
		/**
		 * 
		 * @param	subscriberP
		 * @param	callbackP
		 * @param	priority
		 */
		public function subscribe(subscriberP:ISubscriber, callbackP:Function, priority:int = 0):void 
		{
			addObject(new SubscriberObject(subscriberP, callbackP, Broker.internalID, priority));
			_mapperList.sort(order);
		}
		
		public function unSubscribe(subscriberP:ISubscriber, callbackP:Function):void 
		{
			for (var i:String in _mapper) {
				var t:SubscriberObject = _mapper[i];
				if (t.subscriber == subscriberP && t.method == callbackP) {
					if(Broker.debug) { _trace("NOTE: Subscription intID [" + t.key + "] with SCOPE:" + t.subscriber + " was removed", this, 0xFF00FF) };
					removeObject(t.key);
				}
			}
		}
		
		/**
		 * 
		 */
		public function unSubscribeAll():void 
		{
			var obj:SubscriberObject;
			var L:int = _mapperList.length;
			for (var i:int = 0; i < L ; i++) 
			{
				unSubscribe(obj.subscriber, obj.method);
			}
		}
		
		/**
		 * 
		 */
		public function printSubscribers():void 
		{
			_trace("PUBLISHER:[" + _publisher + "]  SERVICE:[" + _service + "]", this, 0x804000);
			var L:int = _mapperList.length;
			if (L == 0) {
				_trace("       No subscribers found", this, 0xFF00FF);
				return;
			}

			for (var i:int = 0; i < L ; i++) 
			{
				_trace("     " + i + ") Subcsriber METHOD:" + SubscriberObject(_mapperList[i]).subscriber, this, 0x804000);
			}
		}
		
		/**
		 * 
		 * @return
		 */
		public function returnSubscribers():Dictionary 
		{
			return _mapper;
		}
		
		/* INTERFACE org.yawnage.base.interfaces.IMapperObject */
		
		public function get key():String 
		{
			return _service;
		}
		
		/**
		 * 
		 */
		public function get numberSubscribers():Number 
		{
			//_trace(publisher);
			//_trace(_mapperList);
			return _mapperList.length;
		}
		
		/**
		 * 
		 */
		public function get publisher():String 
		{
			return _publisher;
		}
		
		/**
		 * 
		 */
		public function get service():String 
		{
			return _service;
		}
		
		/**
		 * 
		 * @param	a
		 * @param	b
		 * @return
		 */
		private function order(a:SubscriberObject, b:SubscriberObject):int 
		{
			if (a.priority > b.priority) {
				return -1;
			}else if (a.priority < b.priority) {
				return 1;
			}
			return 0;
		}
		
	}
}